﻿using AutoMapper;
using HZY.Quartz.Common;
using HZY.Quartz.Dto;
using HZY.Quartz.Entitys;
using Microsoft.Extensions.Configuration;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace HZY.Quartz.Service.Impl
{
    /// <summary>
    /// 任务服务
    /// </summary>
    public class TaskService : ITaskService
    {
        private readonly IDataService _fileDataService;
        private readonly IProjectService _projectService;
        private readonly IMapper _mapper;
        private readonly IQuartzJobService _quartzJobService;

        public TaskService(IDataService fileDataService,
            IProjectService projectService,
            IMapper mapper,
            IQuartzJobService quartzJobService,
            IDataStorageConfigurationService dataStorageConfigurationService)
        {
            _fileDataService = fileDataService;
            //初始化 FileData服务
            _fileDataService.Init(dataStorageConfigurationService.GetTasksPathOrKey());
            _projectService = projectService;
            _mapper = mapper;
            _quartzJobService = quartzJobService;
        }

        public async Task<IEnumerable<Tasks>> FindListAsync(Guid? projectId)
        {
            var data = await _fileDataService.ReadDataAsync<Tasks>();

            data ??= new List<Tasks>();

            if (projectId != null && projectId != Guid.Empty && data != null)
            {
                data = data.Where(w => w.ProjectId == projectId);
            }

            return data?.OrderBy(w => w.ProjectId)
                 .ThenBy(w => w.GroupName)
                 .ThenBy(w => w.Name)
                 .ThenBy(w => w.CreateTime)
                 .ToList()
                  ?? new List<Tasks>()
                 ;
        }

        public async Task<Tasks> SaveAsync(Tasks form)
        {
            if (!form.Cron.IsValidExpression())
            {
                throw new MessageBox("任务 Cron 时间规则不正确!");
            }

            var data = (await this.FindListAsync(Guid.Empty))?.ToList() ?? new List<Tasks>();
            var projects = await _projectService.FindListAsync();
            var project = projects.FirstOrDefault(w => w.Id == form.ProjectId);
            var tasksByProjectId = await this.FindListAsync(form.ProjectId);

            var tasks = data.Find(w => w.Id == form.Id);

            var isRun = false;

            if (tasks == null)
            {
                if (tasksByProjectId.Any(w => w.Name == form.Name))
                {
                    throw new MessageBox($"任务名称{form.Name} , 已存在！");
                }

                form.Id = Guid.NewGuid();
                tasks = _mapper.Map<Tasks, Tasks>(form);
                tasks.CreateTime = DateTime.Now;
                tasks.ProjectName = project?.Name;
                data.Add(tasks);
            }
            else
            {
                isRun = tasks.State == StateEnum.运行中 && form.State == StateEnum.运行中;

                //验证是否在运行状态
                //if (tasks.State == StateEnum.运行中 && form.State == StateEnum.运行中)
                //{
                //    throw new MessageBox("任务运行中，请先关闭在修改!");
                //}

                if (tasksByProjectId.Any(w => w.Name == form.Name && w.Id != tasks.Id))
                {
                    throw new MessageBox($"任务名称{form.Name} , 已存在！");
                }

                tasks = _mapper.Map(form, tasks);

                if (isRun)
                {
                    await this.CloseByIdAsync(tasks.Id ?? Guid.Empty);
                    tasks.State = StateEnum.未运行;
                }
            }

            await _fileDataService.WriteDataAsync(data);

            if (isRun)
            {
                await RunByIdAsync(tasks.Id ?? Guid.Empty);
            }

            return tasks;
        }

        public async Task<bool> DeleteAsync(Guid id)
        {
            var data = (await this.FindListAsync(Guid.Empty))?.ToList() ?? new List<Tasks>();
            var tasks = data.Find(w => w.Id == id);
            if (tasks == null) return true;

            //验证是否在运行状态
            if (tasks.State == StateEnum.运行中)
            {
                await this.CloseByIdAsync(id);
            }

            data.RemoveAt(data.IndexOf(tasks));

            await _fileDataService.WriteDataAsync(data);

            return true;
        }

        /// <summary>
        /// 根据Id 查询 任务
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public async Task<Tasks> FindByIdAsync(Guid id)
        {
            var data = (await this.FindListAsync(Guid.Empty))?.ToList() ?? new List<Tasks>();
            return data.Find(w => w.Id == id) ?? new Tasks();
        }

        /// <summary>
        /// 根据任务id 运行任务调度
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public async Task<bool> RunByIdAsync(Guid id)
        {
            if (id == Guid.Empty) return true;

            var data = await this.FindByIdAsync(id);

            if (data.State == StateEnum.运行中)
            {
                return true;
            }

            var result = await _quartzJobService.RunAsync(data);

            if (result)
            {
                data.State = StateEnum.运行中;
            }

            await this.SaveAsync(data);

            return result;
        }

        /// <summary>
        /// 根据任务id 关闭任务调度
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public async Task<bool> CloseByIdAsync(Guid id)
        {
            var data = await this.FindByIdAsync(id);

            if (data.State == StateEnum.未运行)
            {
                return true;
            }

            bool result = false;

            try
            {
                result = await _quartzJobService.CloseAsync(data);
            }
            catch (Exception ex)
            {
                //tasks.State = StateEnum.未运行;
                //await _taskService.SaveAsync(tasks);
                throw new MessageBox(ex.Message);
            }
            finally
            {
                //if (result)
                //{
                //    data.State = StateEnum.未运行;
                //}
                data.State = StateEnum.未运行;
                await this.SaveAsync(data);
            }

            return result;
        }

        /// <summary>
        /// 更新执行时间
        /// </summary>
        /// <param name="tasksId"></param>
        /// <param name="dateTime"></param>
        /// <returns></returns>
        public async Task<bool> UpdateExecuteTime(Guid tasksId, DateTime dateTime)
        {
            var data = (await this.FindListAsync(Guid.Empty))?.ToList() ?? new List<Tasks>();

            if (data == null || data.Count == 0) return false;

            var tasks = data.Find(w => w.Id == tasksId);
            if (tasks == null) return false;
            tasks.ExecuteTime = dateTime;
            return await _fileDataService.WriteDataAsync(data);
        }
    }
}
